home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 2005-2009 Pearl Crescent, LLC. All Rights Reserved. */
- /* vim: set sw=2 sts=2 ts=8 et syntax=javascript: */
-
- /*
- * This file is part of the Pearl Crescent Utility Functions Library.
- */
-
- if (!com) var com = {};
- if (!com.aviary) com.aviary = {};
- if (!com.aviary.talon) com.aviary.talon = {};
- if (!com.aviary.talon.pearlutil) com.aviary.talon.pearlutil = {
- kPropBundleURI : "chrome://aviary/locale/extension.properties",
- kStringBundleCID : "@mozilla.org/intl/stringbundle;1",
- kStringBundleInterface : Components.interfaces.nsIStringBundleService,
- kMaxScrollbarSize : 40, // We assume no scrollbar is wider than this.
- kLogPrefix: "Aviary",
-
- // Settings:
- mDebugLevel: 0, // to set this, call SetDebugLevel()
-
- // Cached values:
- mStringBundle: null,
- mAppVersion: 0,
- mConsoleSvc: null,
- mHorzScrollBarHeight: 0,
- _mPrefService: null,
-
- get mPrefService()
- {
- if (!this._mPrefService)
- {
- this._mPrefService = Components
- .classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
- }
-
- return this._mPrefService;
- },
-
- // Returns the major version only, e.g, 2.
- GetAppVersion: function()
- {
- if (0 == this.mAppVersion)
- try
- {
- var v = Components.classes["@mozilla.org/xre/app-info;1"]
- .getService(Components.interfaces.nsIXULAppInfo).version;
- this.mAppVersion = parseInt(v);
- } catch (e) {}
-
- return this.mAppVersion;
- },
-
- // Pass null for aWindow to center on screen.
- Alert: function(aWindow, aMsg)
- {
- try
- {
- var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
- .getService(Components.interfaces.nsIPromptService);
- ps.alert(aWindow, this.GetLocalizedString("ALERT_TITLE"), aMsg);
- }
- catch (e)
- {
- alert(aMsg);
- }
- },
-
- OpenURL: function(aURL, aEvent, aInNewTab)
- {
- if (aURL)
- {
- var tabBrowser = top.getBrowser();
- if (aInNewTab)
- {
- var newtab = window.openNewTabWith(aURL, null, null, aEvent, false);
- if (newtab)
- tabBrowser.selectedTab = newtab;
- }
- else
- tabBrowser.loadURI(aURL);
- }
- },
-
- // Returns true if a new window was opened.
- OpenXULWindow: function(aWindowType, aChromeURL, aFeatures, aArg)
- {
- if (!aChromeURL)
- return false;
-
- var winMed = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
- if (winMed && aWindowType)
- {
- var win = winMed.getMostRecentWindow(aWindowType);
- if (win)
- {
- win.focus();
- return false;
- }
- }
-
- window.openDialog(aChromeURL, "_blank", aFeatures, aArg);
- return true;
- },
-
- // Returns true if a new window was opened.
- OpenPrefsWindow: function(aPrefWindowType, aChromeURL)
- {
- var features = "dialog=no,chrome,titlebar,toolbar";
- var doInstantApply = this.GetBoolPref("browser.preferences.instantApply",
- false);
- if (!doInstantApply)
- features += ",modal";
-
- return this.OpenXULWindow(aPrefWindowType, aChromeURL, features, null);
- },
-
- /*
- * If aBeforeID is present, add the toolbar item aItemID before it.
- * If aBeforeID is not present, add the item to the end of the toolbar
- * identified by aToolbarID.
- * Returns: true if item added to a toolbar (or if it was already present).
- */
- ShowToolbarItem: function(aDoc, aItemID, aBeforeID, aToolbarID)
- {
- var itemElem = aDoc.getElementById(aItemID);
- if (itemElem)
- return true; // Already present.
-
- var tbElem;
- var beforeElem = aBeforeID ? aDoc.getElementById(aBeforeID) : null;
- if (beforeElem)
- tbElem = beforeElem.parentNode;
- if (!tbElem)
- tbElem = aDoc.getElementById(aToolbarID);
- if (tbElem)
- {
- var newSet;
- if (!tbElem.currentSet)
- newSet = aItemID;
- else
- {
- var start = tbElem.currentSet.indexOf(aBeforeID);
- if (start == 0)
- newSet = aItemID + "," + tbElem.currentSet;
- else if (start > 0)
- {
- newSet = tbElem.currentSet.substring(0, start) + aItemID
- + "," + tbElem.currentSet.substring(start);
- }
- else
- newSet = tbElem.currentSet + "," + aItemID;
- }
-
- // Remove search.xml#searchbar observer before setting currentSet.
- // See Mozilla bug #230086 (Destructor of XBL element isn't called...)
- try
- {
- var elem = document.getElementById("searchbar");
- if (elem && elem.parentNode && ((elem.parentNode == tbElem) ||
- (elem.parentNode.parentNode == tbElem)))
- {
- var obsSvc = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
- obsSvc.removeObserver(elem, "browser-search-engine-modified");
- }
- }
- catch (e) {}
-
- tbElem.setAttribute("currentset", newSet);
- tbElem.currentSet = newSet;
- aDoc.persist(tbElem.getAttribute("id"), "currentset");
- return true;
- }
-
- return false; // Not added.
- }, // ShowToolbarItem()
-
- GetLocalizedString: function(aStringName)
- {
- try
- {
- if (!this.mStringBundle)
- {
- this.mStringBundle = Components.classes[this.kStringBundleCID]
- .getService(this.kStringBundleInterface)
- .createBundle(this.kPropBundleURI);
- }
-
- return this.mStringBundle.GetStringFromName(aStringName);
- } catch(e) {}
-
- return aStringName;
- },
-
- GetFormattedLocalizedString: function(aStringName, aArray, aLen)
- {
- try
- {
- if (!this.mStringBundle)
- {
- this.mStringBundle = Components.classes[this.kStringBundleCID]
- .getService(this.kStringBundleInterface)
- .createBundle(this.kPropBundleURI);
- }
-
- return this.mStringBundle.formatStringFromName(aStringName, aArray, aLen);
- } catch(e) {}
-
- return aStringName;
- },
-
- GetFirstChildText: function(aParentElem, aTagName)
- {
- var e = this.PearlGetFirstElementByTagName(aParentElem, aTagName);
- return this.GetNodeText(e);
- },
-
- GetNodeText: function(aNode)
- {
- if (aNode)
- {
- var node = aNode.firstChild;
- if (node &&
- (node.nodeType == Components.interfaces.nsIDOMNode.TEXT_NODE ||
- node.nodeType == Components.interfaces.nsIDOMNode.CDATA_SECTION_NODE))
- {
- return node.nodeValue;
- }
- }
-
- return "";
- },
-
- PearlGetFirstElementByTagName: function(aParentElem, aTagName)
- {
- var firstElem;
-
- if (aParentElem && aTagName)
- {
- var elemList = aParentElem.getElementsByTagName(aTagName);
- if (elemList && elemList.length > 0)
- firstElem = elemList.item(0);
- }
-
- return firstElem;
- },
-
- // GetElementsByAttr() is used by pearlutil-grab.js
- // Returns an array of elements or null if no elements were found.
- // aValue may be null, in which case the value is not checked.
- GetElementsByAttr: function(aContainerElem, aAttr, aValue)
- {
-
- var elemArray = new Array();
- this._GetElementsByAttr(aContainerElem, aAttr, aValue, elemArray);
- return (elemArray.length > 0) ? elemArray : null;
- },
-
- _GetElementsByAttr: function(aContainerElem, aAttr, aValue, aElemArray)
- {
- if (!aContainerElem || !aAttr || !aElemArray)
- return;
-
- for (var childElem = aContainerElem.firstChild; childElem;
- childElem = childElem.nextSibling)
- {
- if (childElem.hasAttribute(aAttr)
- && (!aValue || aValue == childElem.getAttribute(aAttr)))
- {
- aElemArray.push(childElem);
- }
-
- if (childElem.firstChild)
- this._GetElementsByAttr(childElem, aAttr, aValue, aElemArray);
- }
- },
-
- SetElementText: function(aElem, aText)
- {
- if (!aElem)
- return;
-
- var node = aElem.firstChild;
- if (node)
- aElem.removeChild(node);
-
- if (aText && aText.length > 0)
- {
- var textNode = document.createTextNode(aText);
- if (textNode)
- aElem.appendChild(textNode);
- }
- },
-
- SetElementValue: function(aElem, aValue)
- {
- if (!aElem)
- return;
- if (!aValue || aValue.length == 0)
- aValue = "";
- aElem.value = aValue;
- },
-
- SetElementAttribute: function(aElemID, aAttr, aValue)
- {
- var e = document.getElementById(aElemID);
- if (e)
- {
- if (aValue)
- e.setAttribute(aAttr, aValue);
- else
- e.removeAttribute(aAttr);
- }
- },
-
- GetElementAttribute: function(aElemID, aAttr, aDefaultValue)
- {
- var e = document.getElementById(aElemID);
- var retVal = "";
- if (e && aAttr)
- retVal = e.getAttribute(aAttr);
- if (!retVal)
- retVal = aDefaultValue;
-
- return retVal;
- },
-
- EnableElement: function(aID, aIsEnabled)
- {
- this.SetElementAttribute(aID, "disabled", !aIsEnabled);
- },
-
- GetTopBrowserWindow: function()
- {
- var winMed = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
- var winList = winMed.getZOrderDOMWindowEnumerator("navigator:browser",
- true);
- if (!winList.hasMoreElements())
- return top.getBrowser().contentWindow; // fallback
-
- return winList.getNext().getBrowser().contentWindow;
- },
-
- HasClipboardData: function(aMimeType)
- {
- if (!aMimeType)
- return false;
-
- try
- {
- const knsIClipboard = Components.interfaces.nsIClipboard;
-
- var cbSvc = Components.classes["@mozilla.org/widget/clipboard;1"]
- .getService(knsIClipboard);
- var typeArray = [ aMimeType ];
- return cbSvc.hasDataMatchingFlavors(typeArray, typeArray.length,
- knsIClipboard.kGlobalClipboard);
-
- } catch (e) {}
-
- return false;
- },
-
- // aMimeType might be: "image/png" or "image/jpg"
- // This currently works for image types but not string types.
- GetClipboardAsDataURI: function(aMimeType)
- {
- if (!aMimeType)
- return null;
-
- try
- {
- const knsIClipboard = Components.interfaces.nsIClipboard;
- const knsIInputStream = Components.interfaces.nsIInputStream;
- const knsIBinaryInputStream = Components.interfaces.nsIBinaryInputStream;
-
- var cbSvc = Components.classes["@mozilla.org/widget/clipboard;1"]
- .getService(knsIClipboard);
- var xfer = Components.classes["@mozilla.org/widget/transferable;1"]
- .createInstance(Components.interfaces.nsITransferable);
- xfer.addDataFlavor(aMimeType);
- cbSvc.getData(xfer, knsIClipboard.kGlobalClipboard);
- var typeObj = {}, dataObj = {}, lenObj = {};
- xfer.getAnyTransferData(typeObj, dataObj, lenObj);
-
- // TODO: handle string types (they do not have input streams).
- var imgStream = dataObj.value.QueryInterface(knsIInputStream);
- var binStream = Components.classes["@mozilla.org/binaryinputstream;1"]
- .createInstance(knsIBinaryInputStream);
- binStream.setInputStream(imgStream);
-
- var len = binStream.available();
-
- return "data:" + aMimeType + ";base64," + btoa(binStream.readBytes(len));
- }
- catch(e) {}
-
- return null;
- },
-
- // Return height of window client area.
- GetWindowHeight: function(aWindow, aEntirePage)
- {
- /*
- * Use offsetHeight of document element unless it is too small (for example,
- * some pages have an offsetHeight 20 even though scrollMaxY is large).
- * Our fallback is to use window.innerHeight which will be too large if a
- * horizontal scrollbar is present.
- *
- * Avoid docElement.clientHeight because in standards compliance mode it
- * only includes the visible height.
- */
- var height = -1;
- try
- {
- var hasHorzSB = (aWindow.scrollMaxX > 0);
- var sbMaxHeight = (hasHorzSB) ? this.kMaxScrollbarSize : 0;
- var altWinHeight = aWindow.innerHeight + aWindow.scrollMaxY - sbMaxHeight;
-
- var docElement = aWindow.document.documentElement;
- if (docElement && docElement.offsetHeight
- && docElement.offsetHeight > aWindow.scrollMaxY
- && altWinHeight <= docElement.offsetHeight)
- {
- // Ideal Calculation of window's height.
- height = docElement.offsetHeight;
- if (!aEntirePage)
- height -= aWindow.scrollMaxY;
- }
-
- if (height < 0)
- {
- // Alternate calculation (includes height of horz scrollbar if unknown).
- if (hasHorzSB && 0 == this.mHorzScrollBarHeight) try
- {
- // Add hidden element with height=100% and use to determine SB height.
- var tmpElem = aWindow.document.createElement("div");
- tmpElem.setAttribute("style", "visibility: hidden; z-index: -1;"
- + " position: fixed; top: 0px; left: 0px;"
- + " margin: 0px; padding: 0px; border: none;"
- + " width: 100%; height: 100%");
- aWindow.document.body.appendChild(tmpElem);
- var h = aWindow.innerHeight - tmpElem.offsetHeight;
- if (h > 0 && h < this.kMaxScrollbarSize)
- this.mHorzScrollBarHeight = h;
- aWindow.document.body.removeChild(tmpElem);
- } catch (e) {}
-
- height = aWindow.innerHeight; // Includes height of horz. SB if present.
- if (hasHorzSB && this.mHorzScrollBarHeight > 0)
- height -= this.mHorzScrollBarHeight;
- if (aEntirePage)
- height += aWindow.scrollMaxY;
- }
- } catch(e) {}
-
- if (height < 0)
- height = 0;
-
- return height;
- },
-
- // Return width of window client area.
- GetWindowWidth: function(aWindow, aEntirePage)
- {
- var browserWidth = 0;
- try
- {
- browserWidth = aWindow.innerWidth; // our fallback
- var docElement = aWindow.document.documentElement;
- if (docElement && docElement.clientWidth)
- browserWidth = docElement.clientWidth; // usually more accurate
-
- if (aEntirePage)
- browserWidth += aWindow.scrollMaxX;
- } catch(e) {}
-
- // dump("GetWindowWidth(): returning width: " + browserWidth + "\n");
- return browserWidth;
- },
-
- // Compute offset from top-left corner of document (recursive function).
- // Use this like so: var topLeft = this.GetOffsetsForNode(node, null);
- // The result (topLeft) will contain two properties: top, left.
- GetOffsetsForNode: function(aNode, aTopLeftPt)
- {
- if (!aTopLeftPt)
- {
- aTopLeftPt = new Object();
- aTopLeftPt.left = 0;
- aTopLeftPt.top = 0;
- }
-
- if (!aNode)
- return aTopLeftPt;
-
- aTopLeftPt.left += aNode.offsetLeft;
- aTopLeftPt.top += aNode.offsetTop;
- return this.GetOffsetsForNode(aNode.offsetParent, aTopLeftPt);
- },
-
- SanitizeFileName: function(aName)
- {
- var fileName = null;
- if (aName && aName.length > 0)
- {
- fileName = aName.replace(/[\/\\:]/g, "-");
- fileName = fileName.replace(/[\*\?\"\<\>\|]+/g, "");
- fileName = fileName.replace(/^\s+|\s+$/g, "");
- fileName = fileName.substring(0, 216); // Windows limitation
- }
-
- if (!fileName || 0 == fileName.length)
- fileName = this.GetLocalizedString("SUGGESTED_FILE_PREFIX");
-
- return fileName;
- },
-
- // Find a file that does not exist within the directory named by aDirKey.
- // Returns an nsILocalFile or null.
- // The file name will be: aFileBaseName + ' ' + <number> + aFileExt,
- // e.g., "My Picture 1.png"
- // If all files named using 1-99 exist, a name without the space or a
- // number is used.
- // aDirKey may be "Desk" or any of the constants defined in
- // xpcom/io/nsDirectoryServiceDefs.h
- GetFileLocation: function(aDirKey, aFileBaseName, aFileExt)
- {
- var fileLoc = null;
- if (aDirKey && aFileBaseName && aFileExt)
- try {
- var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties);
- var dirLoc = dirSvc.get(aDirKey, Components.interfaces.nsILocalFile);
- var fileLoc = null;
- for (var i = 1; (null == fileLoc) && i < 100; ++i)
- {
- var tmpLoc = dirLoc.clone();
- tmpLoc.append(aFileBaseName + ' ' + i + aFileExt);
- if (!tmpLoc.exists())
- fileLoc = tmpLoc;
- }
-
- if (!fileLoc)
- {
- fileLoc = dirLoc.clone();
- fileLoc.append(aFileBaseName + aFileExt);
- }
- } catch (e) {}
-
- return fileLoc;
- },
-
- // Display the "Save As" dialog. aFile is an nsILocalFile which, if non-null,
- // specifies the starting directory and default file name.
- FilePickerSaveAs: function(aPrompt, aFilterName, aFileExt, aFile)
- {
- var fileLoc = null;
- try
- {
- const knsIFilePicker = Components.interfaces.nsIFilePicker;
- var filePicker = Components.classes["@mozilla.org/filepicker;1"]
- .createInstance(knsIFilePicker);
- filePicker.init(window, aPrompt, knsIFilePicker.modeSave);
- filePicker.appendFilter(aFilterName, '*' + aFileExt);
- filePicker.defaultExtension = aFileExt.substring(1);
- if (aFile)
- {
- filePicker.displayDirectory = aFile.parent;
- filePicker.defaultString = aFile.leafName;
- }
-
- var rv = filePicker.show();
- if (knsIFilePicker.returnCancel != rv)
- fileLoc = filePicker.file;
- } catch (e) {}
-
- return fileLoc;
- },
-
- // Returns 0 if successful and an nserror code if not.
- WriteStreamToFile: function(aSourceStream, aDestFile)
- {
- var resultCode = 0;
-
- try
- {
- var fileOutStream =
- Components.classes["@mozilla.org/network/file-output-stream;1"]
- .createInstance(Components.interfaces.nsIFileOutputStream);
- const kWriteOnly = 0x02; // see prio.h
- const kCreateFile = 0x08;
- const kTruncate = 0x20;
- var flags = kWriteOnly | kCreateFile | kTruncate;
- fileOutStream.init(aDestFile, flags, 0666, false);
-
- const kIOBlockSize = 65536;
- var remaining = aSourceStream.available();
- while (remaining > 0)
- {
- var count = (remaining > kIOBlockSize) ? kIOBlockSize : remaining;
- var binData = aSourceStream.readBytes(count);
- fileOutStream.write(binData, count);
- remaining -= count;
- }
-
- fileOutStream.close();
- }
- catch (e)
- {
- dump("WriteStreamToFile error: " + e + "\n"); // log to aid debugging
- resultCode = e.result;
- }
-
- return resultCode;
- },
-
- // Preference related functions that do not throw.
- PrefHasUserValue: function(aPrefName)
- {
- try
- {
- return this.mPrefService.prefHasUserValue(aPrefName);
- } catch (e) {}
-
- return false;
- },
-
- ClearUserPref: function(aPrefName)
- {
- try
- {
- this.mPrefService.clearUserPref(aPrefName);
- } catch (e) {}
- },
-
- GetBoolPref: function(aPrefName, aDefaultValue /* = false */)
- {
- try
- {
- return this.mPrefService.getBoolPref(aPrefName);
- } catch (e) {}
-
- return (aDefaultValue != undefined) ? aDefaultValue : false;
- },
-
- SetBoolPref: function(aPrefName, aValue)
- {
- try
- {
- this.mPrefService.setBoolPref(aPrefName, aValue);
- } catch (e) {}
- },
-
- GetIntPref: function(aPrefName, aDefaultValue /* = 0 */)
- {
- try
- {
- return this.mPrefService.getIntPref(aPrefName);
- } catch (e) {}
-
- return (aDefaultValue != undefined) ? aDefaultValue : 0;
- },
-
- SetIntPref: function(aPrefName, aValue)
- {
- try
- {
- this.mPrefService.setIntPref(aPrefName, aValue);
- } catch (e) {}
- },
-
- GetASCIIPref: function(aPrefName, aDefaultValue /* = null */)
- {
- try
- {
- return this.mPrefService.getCharPref(aPrefName);
- } catch (e) {}
-
- return (aDefaultValue != undefined) ? aDefaultValue : null;
- },
-
- SetASCIIPref: function(aPrefName, aValue)
- {
- try
- {
- this.mPrefService.setCharPref(aPrefName, aValue);
- } catch (e) {}
- },
-
- GetLocalizedStrPref: function(aPrefName, aDefaultValue /* null */)
- {
- try
- {
- return this.mPrefService.getComplexValue(aPrefName,
- Components.interfaces.nsIPrefLocalizedString).data;
- } catch (e) {}
-
- return (aDefaultValue != undefined) ? aDefaultValue : null;
- },
-
- SetLocalizedStrPref: function(aPrefName, aValue)
- {
- try
- {
- const kISupStr = Components.interfaces.nsISupportsString;
- var ss = Components.classes["@mozilla.org/supports-string;1"]
- .createInstance(kISupStr);
- ss.data = aValue;
- this.mPrefService.setComplexValue(aPrefName, kISupStr, ss);
- } catch (e) {}
- },
-
- SetDebugLevel: function(aLevel)
- {
- this.mDebugLevel = aLevel;
- },
-
- TraceLog: function(aLevel, aModuleName, aMsg)
- {
- const doIncludeTimestamp = false;
-
- if (aLevel <= this.mDebugLevel)
- {
- if (!this.mConsoleSvc) try
- {
- this.mConsoleSvc = Components.classes["@mozilla.org/consoleservice;1"]
- .getService(Components.interfaces.nsIConsoleService);
- }
- catch (e) {}
-
- if (this.mConsoleSvc)
- {
- if (!aModuleName)
- aModuleName = "";
-
- var s = this.kLogPrefix + " ";
- if (doIncludeTimestamp)
- s += new Date().toLocaleString() + ' ';
- s += aModuleName + ": " + aMsg;
- this.mConsoleSvc.logStringMessage(s);
- dump(s + "\n");
- }
- }
- },
-
- endOfObject: true
- }
-